package com.ruoyi.system.utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;

public class HMACSHA1Util {

    private static final String ALGORITHM = "HmacSHA1";

    /**
     * 使用 HMAC-SHA1 算法生成签名
     *
     * @param data 要加密的数据 (例如: appId + appKey + timeStamp)
     * @param key  加密密钥 (例如: appKey)
     * @return 小写的十六进制签名字符串
     */
    public static String sign(String data, String key) {
        try {
            // 1. 获取 Mac 实例，指定算法为 HmacSHA1
            Mac mac = Mac.getInstance(ALGORITHM);

            // 2. 创建密钥规范(SecretKeySpec)
            //    关键点: 必须将密钥字符串按 UTF-8 编码转换为字节数组
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);

            // 3. 使用密钥初始化 Mac 实例
            mac.init(secretKey);

            // 4. 计算 HMAC
            //    关键点: 必须将待加密数据按 UTF-8 编码转换为字节数组
            byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));

            // 5. 将计算出的字节数组转换为小写的十六进制字符串
            return bytesToHexString(rawHmac);

        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            // 在实际项目中，这里应该记录详细的错误日志
            e.printStackTrace();
            throw new RuntimeException("HMAC-SHA1 签名生成失败", e);
        }
    }

    /**
     * 将字节数组转换为十六进制字符串 (小写)
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            // 将每个字节转换为两位十六进制数
            // String.format("%02x", ...) 确保每个字节都输出两位，不足的用 0 填充
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}